﻿using PublishRepository;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace TFPublish
{
	public partial class PublishForm : Form
	{

		private ConfigEntity _configEntity;
		private List<ServiceEntity> _selectedServiceEntity = new List<ServiceEntity>();

		public PublishForm()
		{
			InitializeComponent();
		}

		private void PublishForm_Load(object sender, EventArgs e)
		{
			SetUpServices();
		}

		private void btnPublish_Click(object sender, EventArgs e)
		{
			if (gvServices.SelectedRows.Count == 0)
			{
				MessageBox.Show("Please select a service to publish");
				return;
			}
			var start = DateTime.Now;
			txtStatus.Text += $"Start Publish {string.Join(", ", _selectedServiceEntity.Select(x => x.ServiceName).ToList())}... \r\n";
			btnPublish.Enabled = false;

			if (_selectedServiceEntity.Exists(x => x.Type == ServiceType.web))
			{
				ZipWebTask();
			}

			if (_selectedServiceEntity.Exists(x => x.Type == ServiceType.api))
			{
				ZipApiTask();
			}
			txtStatus.Text += "zip finish \r\n";
			txtStatus.Text += "start upload \r\n";
			var tasks = new List<Task>();

			_selectedServiceEntity.ForEach(service =>
			{
				Task task = new Task(() => { });

				if (service.Type == ServiceType.web)
				{
					task = new Task(() =>
					{
						PostWebTask(service);
					});

				}
				else if (service.Type == ServiceType.api)
				{
					task = new Task(() =>
					{
						PostApiTask(service);
					});
				}
				task.Start();
				tasks.Add(task);
			});
			Task.WaitAll(tasks.ToArray());
			var end = DateTime.Now;
			txtStatus.Text += "Finish\r\n";
			txtStatus.Text += end + "\r\n";
			TimeSpan duration = end - start;
			txtStatus.Text += "total " + duration.TotalSeconds + " seconds \r\n\r\n";
			txtStatus.SelectionStart = txtStatus.TextLength;
			txtStatus.ScrollToCaret();
			btnPublish.Enabled = true;

			SaveLastPublish();
			MessageBox.Show($"Finish total {duration.TotalSeconds} seconds");
		}

		private void ZipWebTask()
		{
			Utility.RunWebTask(txtTaskFolder.Text);
			Utility.ZipWeb(_configEntity.WebCodeFolder + @"\build", "build.zip");
		}

		private void ZipApiTask()
		{
			Utility.ZipApi(_configEntity.ApiCodeFolder + @"\RoutefinderApi\bin", "bin.zip");
		}

		private async void PostWebTask(ServiceEntity service)
		{
			await Utility.Post(service.Url + "?binPath=" + service.UnzipFolder, _configEntity.WebCodeFolder + @"\build\build.zip");
		}

		private async void PostApiTask(ServiceEntity service)
		{
			await Utility.Post(service.Url + "?binPath=" + service.UnzipFolder, _configEntity.ApiCodeFolder + @"\RoutefinderApi\bin\bin.zip");
		}


		private void SetUpServices()
		{
			_configEntity = ConfigEntity.Load();
			txtApiFolder.Text = _configEntity.ApiCodeFolder;
			txtCoreFolder.Text = _configEntity.CoreFolder;
			txtTaskFolder.Text = _configEntity.TaskLocation;
			txtWebFolder.Text = _configEntity.WebCodeFolder;

			_configEntity.Services.ForEach(service =>
			{
				gvServices.Rows.Add(new String[] { service.ServiceName, service.Type, service.Url, service.UnzipFolder });
			});
			gvServices.ClearSelection();

			if (_configEntity.LastSelected.Count > 0)
			{
				var services = new List<ServiceEntity>();
				for (var i = 0; i < _configEntity.Services.Count; i++)
				{
					if (_configEntity.LastSelected.Contains(_configEntity.Services[i].ServiceName))
					{
						services.Add(_configEntity.Services[i]);
						gvServices.Rows[i].Selected = true;
					}
				}
				SetSelectedService(services);
			}
		}


		private void gvServices_CellEndEdit(object sender, DataGridViewCellEventArgs e)
		{
			var rowIndex = gvServices.CurrentCell.RowIndex;
			int cellIndex = gvServices.CurrentCell.ColumnIndex;
			var value = gvServices.CurrentCell.Value.ToString();
			ServiceEntity serviceEntity;
			if (_configEntity.Services.Count > rowIndex)
			{
				serviceEntity = _configEntity.Services[rowIndex];
			}
			else
			{
				serviceEntity = new ServiceEntity();
				_configEntity.Services.Add(serviceEntity);
			}
			var service = _configEntity.Services[rowIndex];
			switch (cellIndex)
			{
				case 0:
					service.ServiceName = value;
					break;
				case 1:
					service.Type = value;
					break;
				case 2:
					service.Url = value;
					break;
				case 3:
					service.UnzipFolder = value;
					break;
			}
			ConfigEntity.Save(_configEntity);
		}

		private void gvServices_SelectionChanged(object sender, EventArgs e)
		{
			List<ServiceEntity> services = new List<ServiceEntity>();

			foreach (DataGridViewRow row in gvServices.SelectedRows)
			{
				if (row.Cells[0].Value != null &&
					row.Cells[1].Value != null &&
					row.Cells[2].Value != null &&
					row.Cells[3].Value != null)
				{
					services.Add(new ServiceEntity()
					{
						ServiceName = row.Cells["ServiceName"].Value.ToString(),
						Type = row.Cells["Type"].Value.ToString(),
						Url = row.Cells["Url"].Value.ToString(),
						UnzipFolder = row.Cells["UnzipFolder"].Value.ToString()
					});
				}
			}
			SetSelectedService(services);
		}

		private void SetSelectedService(List<ServiceEntity> services)
		{
			_selectedServiceEntity = services;
			lblSelectedService.Text = "Selected service： " + string.Join(", ", _selectedServiceEntity.Select(x => x.ServiceName).ToList());
		}

		private void txtWebFolder_TextChanged(object sender, EventArgs e)
		{
			_configEntity.WebCodeFolder = txtWebFolder.Text;
			ConfigEntity.Save(_configEntity);
		}

		private void txtApiFolder_TextChanged(object sender, EventArgs e)
		{
			_configEntity.ApiCodeFolder = txtApiFolder.Text;
			ConfigEntity.Save(_configEntity);
		}

		private void txtCoreFolder_TextChanged(object sender, EventArgs e)
		{
			_configEntity.CoreFolder = txtCoreFolder.Text;
			ConfigEntity.Save(_configEntity);
		}

		private void txtTaskFolder_TextChanged(object sender, EventArgs e)
		{
			_configEntity.TaskLocation = txtTaskFolder.Text;
			ConfigEntity.Save(_configEntity);
		}

		private void gvServices_RowsRemoved(object sender, DataGridViewRowsRemovedEventArgs e)
		{
			_configEntity.Services.RemoveAt(e.RowIndex);
			ConfigEntity.Save(_configEntity);
		}

		private void SaveLastPublish()
		{
			_configEntity.LastSelected = _selectedServiceEntity.Select(x => x.ServiceName).ToList();
			ConfigEntity.Save(_configEntity);
		}

	}
}
